#include <gtest/gtest.h>
#include <arpa/inet.h>
#include "UdpSocketWrapper.hpp"
#include "HiCommonLog.hpp"

using namespace std;

static const char* msg = "this is a test of UdpSocketWrapper";
static int msg_len = ::strlen(msg);
static const char* myIp = "127.0.0.1";

class MyGuardProxy {
public:
	MyGuardProxy() {
		hi_is_ignore_debug(false);
	}
};

static MyGuardProxy proxy;


static void ReceiveMsg(const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketWrapper* wrapper) {
		printf("TEST ReceiveMsg called\n");
		ASSERT_TRUE(wrapper != nullptr);
		ASSERT_TRUE(data != nullptr);
		ASSERT_TRUE(addr != nullptr);
		
		ASSERT_GT(wrapper->GetRecvBytes(), (size_t)0);
		EXPECT_EQ(wrapper->GetSentBytes(), (size_t)0);
		
		struct sockaddr_in* addr_in = static_cast<struct sockaddr_in*>((struct sockaddr_in*)addr);
		
		int port = ntohs(addr_in->sin_port);
		char ip[64] = {0}; 
		struct in_addr in  = addr_in->sin_addr;
		inet_ntop(AF_INET,&in, ip, sizeof(ip));

		cout << "data:" << (const char*)data << 
			", len:" << len << 
			", remote ip:" << ip << 
			", port:" << port << 
			", local ip:" << wrapper->GetLocalIP() <<
			", local port:" << wrapper->GetLocalPort() << endl;
			
		wrapper->Send((const uint8_t*)data, len, addr);	
		sleep(1); 
		wrapper->Send((const uint8_t*)data, len, addr);		
		sleep(1); 
		cout << "send size:" << wrapper->GetSentBytes() << endl;
		
		printf("receive message\n");
		
		//EXPECT_EQ(wrapper->GetRecvBytes(), (size_t)(msg_len * 2));
}

TEST(UdpSocketWrapperTest, listen) {
	UdpSocketWrapper* udp_send = new UdpSocketWrapper();
	int ret = udp_send->Listen(myIp, 60002);
	EXPECT_EQ(ret, 0);
    UdpSocketWrapper* udp = new UdpSocketWrapper();
	ret = udp->Listen(myIp, 60001, ReceiveMsg);
	EXPECT_EQ(ret, 0);
	sleep(1); 
	udp_send->Send((const uint8_t*)msg, msg_len, myIp, 60001);
	
	sleep(2); 
	udp->Destroy();
	udp_send->Destroy();
	sleep(2); 
	delete udp;
	udp = nullptr;
	delete udp_send;
	udp_send = nullptr;
	
	udp = new UdpSocketWrapper();
	ret = udp->Listen(myIp, 60004, [&](const uint8_t* data, size_t len, const struct sockaddr* addr, UdpSocketWrapper* wrapper) {
		printf("TEST ReceiveMsg begin\n");
		ReceiveMsg(data, len, addr, wrapper);
		printf("TEST ReceiveMsg end\n");
	});
	EXPECT_EQ(ret, 0);
	sleep(1); 
	
	udp_send = new UdpSocketWrapper();
	ret = udp_send->Listen(myIp, 60005);
	EXPECT_EQ(ret, 0);
	sleep(1); 
	udp_send->Send((const uint8_t*)msg, msg_len, myIp, 60004);
	
	sleep(2); 
	udp->Destroy();
	udp_send->Destroy();
	sleep(2); 
	//sleep(2000);
	delete udp;
	udp = nullptr;
	delete udp_send;
	udp_send = nullptr;
}

TEST(UdpSocketWrapperTest, destory) {
    UdpSocketWrapper* udp = new UdpSocketWrapper();
	printf(" create UdpSocketWrapper \n");	
	int ret = udp->Listen(myIp, (uint16_t)60003);
	
	EXPECT_EQ(ret, 0);
	
	sleep(1); 
	udp->Destroy();
	sleep(1); 
	delete udp;
	udp = nullptr;
}